package com.knife.member.stat;

import java.sql.*;
import java.util.*;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.Day;

public class StatHandle {
	
	public static void insertEndTime(int viewedid)throws Exception {
		
		Connection cnn = null;
		PreparedStatement ps = null;
		try {
			cnn = DBHandle.getConnection(); // 获取连接句柄
			ps = cnn.prepareStatement("update k_userhistory set k_endtime=? where id=?");
			// 填充参数
			ps.setTime(1, new Time(System.currentTimeMillis()));
			ps.setInt(2, viewedid);
			ps.executeUpdate(); // 执行语句
			cnn.commit();
		} catch (Exception es) {
			throw es;
		} finally {
			DBHandle.closeResource(ps, null, cnn); // 释放语句句柄和连接句柄
		}
		
	}
	
	/**
	 * 往数据库插入新的访问信息
	 * 
	 * @param k_ip
	 *            String 用户IP地址
	 * @param oper
	 *            String
	 * @param k_browser
	 *            String
	 * @throws Exception
	 */
	public static int insert(String k_ip, String k_usermail, String k_os,
			String k_browser, String k_url, int type) throws Exception {
		Connection cnn = null;
		PreparedStatement ps = null;
		int keyValue = -1;
		try {
			cnn = DBHandle.getConnection(); // 获取连接句柄
			ps = cnn.prepareStatement( // 创建语句句柄
			"insert into k_userhistory(k_ip,k_usermail, k_os, k_browser,k_url, k_accessdate, k_accesstime,k_type) values(?,?,?,?,?,?,?,?)", Statement.RETURN_GENERATED_KEYS);
			// 填充参数
			ps.setString(1, k_ip);
			ps.setString(2, k_usermail);
			ps.setString(3, k_os.toUpperCase()); // 存大写
			ps.setString(4, k_browser.toUpperCase());
			ps.setString(5, k_url);
			ps.setDate(6, new java.sql.Date(System.currentTimeMillis()));
			ps.setTime(7, new Time(System.currentTimeMillis()));
			ps.setInt(8, type);
			ps.executeUpdate(); // 执行语句
			ResultSet rs = ps.getGeneratedKeys();
			if (rs.next()) {  
				keyValue = rs.getInt(1);  
			}
			cnn.commit();
		} catch (Exception es) {
			throw es;
		} finally {
			DBHandle.closeResource(ps, null, cnn); // 释放语句句柄和连接句柄
		}
		return keyValue;
	}

	/**
	 * 往数据库插入新的访问信息
	 * 
	 * @param k_os
	 *            String 操作系统
	 * @param k_browser
	 *            String 浏览器
	 */
	public static void insert(String k_os, String k_browser) throws Exception {
		Connection cnn = null;
		PreparedStatement ps = null;
		try {
			cnn = DBHandle.getConn();
			// 获取连接句柄
			ps = cnn.prepareStatement("insert into k_userhistory(k_os, k_browser, k_accessdate, k_accesstime) values(?,?,?,?)");
			// 创建语句句柄
			ps.setString(1, k_os.toUpperCase());
			// 填充语句参数，将操作系统名称保存为大写
			ps.setString(2, k_browser.toUpperCase());
			// 将浏览器名称保存为大写
			ps.setDate(3, new java.sql.Date(System.currentTimeMillis()));
			// 访问日期为当天
			ps.setTime(4, new Time(System.currentTimeMillis()));
			// 访问时间为当时
			ps.executeUpdate();
			// 执行语句，往history表中插入一条记录
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, null, cnn);
			// 释放语句句柄和连接句柄
		}
	}

	/**
	 * 获取当月在内，前几月的访问数据，并保存到数据集（JFreeChart要用到）中
	 * 
	 * @param count
	 *            int 要统计多少天的数据
	 * @return DefaultCategoryDataset 返回数据集，里面包含前count月每月的访问次数
	 */
	public static DefaultCategoryDataset getMonthStat(int count)
			throws Exception {
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		DefaultCategoryDataset chart = new DefaultCategoryDataset();
		// 数据集，用于保存前count月每月的访问次数
		try {
			cnn = DBHandle.getConnection(); // 获取连接句柄
			java.util.Date date = new java.util.Date();
			// 创建日期对象，默认为当前日期
			for (int i = 0; i < count; i++) {
				// 循环count次，依次获取给定月的访问次数并保存在数据集中
				String start = THandle
						.getStartDateofNMonth(date, count - i - 1);
				// 获取前面第(count - i - 1)月的第一天的字符串表示
				// 比如2006年3月份的第一天表示为为“2006-3-1”
				String end = THandle.getEndDateofNMonth(date, count - i - 1);
				// 获取前面第(count - i - 1)月的最后一天的字符串表示
				// 比如2006年3月份的最后一天表示为为“2006-3-31”
				String sql = "select count(*) from k_userhistory";
				sql += " where k_accessdate>='" + start
						+ "' and k_accessdate<='" + end + "'";
				// 获取前面第(count - i - 1)月的访问次数的SQL语句
				// System.out.println(sql);
				// 将SQL语句打印在日志信息中
				ps = cnn.prepareStatement(sql);
				// 使用SQL字符串创建语句句柄
				rs = ps.executeQuery();
				// 执行语句获取结果集
				rs.next();
				// 游标指向结果集中第一条记录
				chart.addValue(rs.getInt(1), "访问量",
						THandle.getNMonth(date, count - i - 1));
				// 将前面第(count - i - 1)月的访问次数保存到数据集中
				DBHandle.closeResource(ps, rs, null);
				// 释放在本次循环中的结果集和语句句柄
			}
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, rs, cnn);
			// 释放连接句柄以及其他未释放的资源
		}
		return chart;
		// 返回数据集
	}

	/**
	 * 获取当天在内，前几天的访问数据，并保存到数据集（JFreeChart要用到）中
	 * 
	 * @param count
	 *            int 要统计多少天的数据
	 * @return XYDataset 返回数据集，里面包含前count天每天的访问次数
	 */
	public static XYDataset getDayStat(int count) throws Exception {
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		TimeSeriesCollection chart = new TimeSeriesCollection();
		// 时间序列对象集合，里面可以存放多个TimeSeries对象，
		// TimeSeriesCollection实现了XYDataset接口
		TimeSeries timeseries = new TimeSeries("日访问", Day.class);
		// 时间序列对象，第一个参数表示时间序列的名字，第二个参数是时间类型，这里为天
		// 该对象用于保存前count天每天的访问次数
		try {
			cnn = DBHandle.getConnection();
			// 获取连接句柄
			java.util.Date date = new java.util.Date();
			// 创建日期对象，默认为当前日期
			for (int i = 0; i < count; i++) {
				// 循环count次，依次获取给定日期的访问次数并保存在数据集中
				String str = THandle.getLastDate(date, count - i - 1);
				// 获取前面第(count - i - 1)天的日期的字符串表示
				String sql = "select count(*) from k_userhistory where k_accessdate='"
						+ str + "'";
				// 获取前面第(count - i - 1)天的访问次数的SQL语句
				// System.out.println(sql);
				// 将SQL语句打印在日志信息中
				ps = cnn.prepareStatement(sql);
				// 使用SQL字符串创建语句句柄
				rs = ps.executeQuery();
				// 执行语句获取结果集
				rs.next();
				// 游标指向结果集中第一条记录
				StringTokenizer st = new StringTokenizer(str, "-");
				// 从日期字符串str中，获取年、月、日
				int year = Integer.parseInt(st.nextToken());
				int month = Integer.parseInt(st.nextToken());
				int day = Integer.parseInt(st.nextToken());
				timeseries.add(new Day(day, month, year), rs.getInt(1));
				// 将前面第(count - i - 1)天的访问次数保存到时间序列对象中
				DBHandle.closeResource(ps, rs, null);
				// 释放在本次循环中的结果集和语句句柄
			}
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, rs, cnn);
			// 释放连接句柄以及其他未释放的资源
		}
		chart.addSeries(timeseries);
		// 将时间序列对象保存到时间序列对象集合中
		return chart;
		// 返回数据集
	}

	/**
	 * 将某一天各个时段的访问数据取出来并保存到数据集中
	 * 
	 * @param data
	 *            DefaultCategoryDataset 数据集
	 * @param date
	 *            String 以字符串表示的日期
	 * @param count
	 *            int 每一天分成多少个时段
	 * @throws Exception
	 */
	public static void setHourStat(DefaultCategoryDataset data, String date,
			int count) throws Exception {
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			cnn = DBHandle.getConnection(); // 获取连接句柄
			int length = 24 / count;
			// 每个时段的长度，比如count = 4,那么每个时段长度为6
			for (int i = 0; i < count; i++) {
				// 循环count次，依次获取每个时段的访问次数
				String start = i * length + ":00:00";
				// 第i个时段的开始时间
				String end = ((i + 1) * length - 1) + ":59:59";
				// 第i个时段的结束时间
				String sql = "select count(*) from k_userhistory";
				sql += " where k_accesstime>='" + start
						+ "' and k_accesstime<='" + end + "'";
				sql += " and k_accessdate='" + date + "'";
				// 获取某一个时段访问量的SQL语句
				// System.out.println(sql);
				// 将SQL语句打印在日志信息中
				ps = cnn.prepareStatement(sql);
				// 使用SQL字符串创建语句句柄
				rs = ps.executeQuery();
				// 执行语句获取结果集
				rs.next();
				// 游标指向结果集中第一条记录
				data.addValue(rs.getInt(1),
						i * length + "-" + (i + 1) * length, date);
				// 将三元组（访问次数，时段，访问日期）保存到数据集中
				DBHandle.closeResource(ps, rs, null);
				// 释放在本次循环中的结果集和语句句柄
			}
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, rs, cnn);
			// 释放连接句柄以及其他未释放的资源
		}
	}

	/**
	 * 获取当天在内，前几天的各个时段的访问数据，并保存到数据集（JFreeChart要用到）中
	 * 
	 * @param dayCount
	 *            int 要统计多少天的数据
	 * @param count
	 *            int 要统计多少个时段的数据
	 * @return DefaultCategoryDataset 返回数据集，里面包含前count天每天的访问次数
	 */
	public static DefaultCategoryDataset getHourStat(int dayCount, int count)
			throws Exception {
		DefaultCategoryDataset data = new DefaultCategoryDataset();
		// 数据集，用于保存每天各个时段的访问数据
		try {
			java.util.Date date = new java.util.Date();
			// 创建日期对象，默认为当前日期
			for (int i = 0; i < dayCount; i++) {
				// 循环dayCount次，获取每天各个时段的访问数据
				String str = THandle.getLastDate(date, dayCount - i - 1);
				// 获取前面第(count - i - 1)天的日期的字符串表示
				setHourStat(data, str, count);
				// 将某一天各个时段的访问数据取出来并保存到数据集中
			}
		} catch (Exception es) {
			throw es;
		}
		return data;
		// 返回数据集
	}

	/**
	 * 获取OS类型统计,并保存到数据集（JFreeChart要用到）中
	 * 
	 * @throws Exception
	 * @return DefaultPieDataset
	 */
	public static DefaultPieDataset getOSStat() throws Exception {
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		DefaultPieDataset data = new DefaultPieDataset();
		// 数据集，用于保存操作系统类型统计数据
		try {
			cnn = DBHandle.getConnection();
			// 获取连接句柄
			String sql = "select distinct k_os from k_userhistory";
			// 从历史记录表中获取操作系统类型
			ps = cnn.prepareStatement(sql);
			// 使用SQL字符串创建语句句柄
			rs = ps.executeQuery();
			// 执行语句获取结果集
			while (rs.next()) {
				String k_os = rs.getString(1);
				// 获取某一类操作系统名称
				sql = "select count(*) from k_userhistory where k_os = '" + k_os + "'";
				// 获取某一名称操作系统的访问次数
				// System.out.println(sql);
				// 将SQL语句打印在日志信息中
				PreparedStatement pss = cnn.prepareStatement(sql);
				// 使用SQL字符串创建语句句柄
				ResultSet rss = pss.executeQuery();
				// 执行语句获取结果集
				rss.next();
				// 游标指向结果集中第一条记录
				data.setValue(k_os, rss.getInt(1));
				// 将二元组（操作系统名字，访问次数）保存到数据集中
				DBHandle.closeResource(pss, rss, null);
				// 释放在本次循环中的结果集和语句句柄
			}
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, rs, cnn);
			// 释放连接句柄以及其他未释放的资源
		}
		return data;
	}

	/**
	 * 获取浏览器类型统计,并保存到数据集（JFreeChart要用到）中
	 * 
	 * @throws Exception
	 * @return DefaultPieDataset
	 */
	public static DefaultPieDataset getBrowserStat() throws Exception {
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		DefaultPieDataset data = new DefaultPieDataset();
		// 数据集，用于保存操作系统类型统计数据
		try {
			cnn = DBHandle.getConnection();
			// 获取连接句柄
			String sql = "select distinct k_browser from k_userhistory";
			// 从历史记录表中获取操作系统类型
			ps = cnn.prepareStatement(sql);
			// 使用SQL字符串创建语句句柄
			rs = ps.executeQuery();
			// 执行语句获取结果集
			while (rs.next()) {
				String k_browser = rs.getString(1);
				// 获取某一类操作系统名称
				sql = "select count(*) from k_userhistory where k_browser = '"
						+ k_browser + "'";
				// 获取某一名称操作系统的访问次数
				// System.out.println(sql);
				// 将SQL语句打印在日志信息中
				PreparedStatement pss = cnn.prepareStatement(sql);
				// 使用SQL字符串创建语句句柄
				ResultSet rss = pss.executeQuery();
				// 执行语句获取结果集
				rss.next();
				// 游标指向结果集中第一条记录
				data.setValue(k_browser, rss.getInt(1));
				// 将二元组（操作系统名字，访问次数）保存到数据集中
				DBHandle.closeResource(pss, rss, null);
				// 释放在本次循环中的结果集和语句句柄
			}
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, rs, cnn);
			// 释放连接句柄以及其他未释放的资源
		}
		return data;
	}

	public static DefaultPieDataset getBrowserStat2() throws Exception {
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		DefaultPieDataset chart = new DefaultPieDataset();
		try {
			cnn = DBHandle.getConnection();
			// 获取连接句柄
			// java.util.Date date = new java.util.Date();
			String sql = "select distinct k_browser from k_userhistory";
			// System.out.println(sql);
			ps = cnn.prepareStatement(sql); // 创建语句句柄
			rs = ps.executeQuery();
			while (rs.next()) {
				String k_browser = rs.getString(1);
				sql = "select count(*) from k_userhistory where k_browser = '"
						+ k_browser + "'";
				//System.out.println(sql);
				PreparedStatement pss = cnn.prepareStatement(sql); // 创建语句句柄
				ResultSet rss = pss.executeQuery();
				rss.next();
				chart.setValue(k_browser, rss.getInt(1));
				DBHandle.closeResource(pss, rss, null);
			}
		} catch (Exception es) {
			throw es;
		} finally {
			DBHandle.closeResource(ps, rs, cnn); // 释放语句句柄和连接句柄
		}
		return chart;
	}

	/**
	 * 查询访问站点次数
	 */
	public static int select() throws Exception {
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		int count = 0;
		try {
			cnn = DBHandle.getConnection();
			// 获取连接句柄
			ps = cnn.prepareStatement("select count(*) from k_userhistory");
			// 创建语句句柄
			rs = ps.executeQuery();
			// 执行查询语句，获取结果集
			rs.next();
			// 游标指向第一条记录
			count = rs.getInt(1);
			// 记录访问次数
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, rs, cnn);
			// 释放语句句柄、连接句柄、结果集
		}
		return count;
	}

	public static List<UserView> getViewList(String k_usermail) throws Exception {
		return getViewList(k_usermail, 0);
	}

	public static List<UserView> getViewList(String k_usermail, int type)
			throws Exception {
		List<UserView> alist = new ArrayList<UserView>();
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			cnn = DBHandle.getConnection();
			// 获取连接句柄
			ps = cnn.prepareStatement("select * from k_userhistory where k_usermail=? and k_type=? order by k_accesstime desc");
			ps.setString(1, k_usermail);
			ps.setInt(2, type);
			// 创建语句句柄
			rs = ps.executeQuery();
			// 执行查询语句，获取结果集
			while (rs.next()) {
				// 游标指向第一条记录
				UserView uv = new UserView();
				uv.setId(rs.getInt("id"));
				uv.setUsermail(rs.getString("k_usermail"));
				uv.setIp(rs.getString("k_ip"));
				uv.setOs(rs.getString("k_os"));
				uv.setBrowser(rs.getString("k_browser"));
				uv.setUrl(rs.getString("k_url"));
				uv.setAccessdate(rs.getDate("k_accessdate"));
				uv.setAccesstime(rs.getTime("k_accesstime"));
				uv.setEndtime(rs.getTime("k_endtime"));
				alist.add(uv);
			}
			// count = rs.getInt(1);
			// 记录访问次数
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, rs, cnn);
			// 释放语句句柄、连接句柄、结果集
		}
		return alist;
	}

	public static boolean hasView(String k_acount, String k_url) {
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			cnn = DBHandle.getConnection();
			// 获取连接句柄
			ps = cnn.prepareStatement("select * from k_userhistory where k_usermail=? and k_url=? limit 0,1");
			ps.setString(1, k_acount);
			ps.setString(2, k_url);
			// 创建语句句柄
			rs = ps.executeQuery();
			return rs.next();
		} catch (Exception es) {
			es.printStackTrace();
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, rs, cnn);
			// 释放语句句柄、连接句柄、结果集
		}
		return false;
	}
	
	public static void removeView(int id)throws Exception{
		Connection cnn = null;
		PreparedStatement ps = null;
		try {
			cnn = DBHandle.getConnection();
			// 获取连接句柄
			ps = cnn.prepareStatement("delete from k_userhistory where id="+id);
			ps.execute();
			cnn.commit();
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, null, cnn);
			// 释放语句句柄、连接句柄、结果集
		}
	}
	
	public static UserView getView(int id)throws Exception{
		UserView uv = new UserView();
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			cnn = DBHandle.getConnection();
			// 获取连接句柄
			ps = cnn.prepareStatement("select * from k_userhistory where id=? order by k_accessdate desc,k_accesstime desc limit 1");
			ps.setInt(1, id);
			// 创建语句句柄
			rs = ps.executeQuery();
			// 执行查询语句，获取结果集
			while (rs.next()) {
				// 游标指向第一条记录
				uv.setId(rs.getInt("id"));
				uv.setUsermail(rs.getString("k_usermail"));
				uv.setIp(rs.getString("k_ip"));
				uv.setOs(rs.getString("k_os"));
				uv.setBrowser(rs.getString("k_browser"));
				uv.setUrl(rs.getString("k_url"));
				uv.setAccessdate(rs.getDate("k_accessdate"));
				uv.setAccesstime(rs.getTime("k_accesstime"));
				uv.setEndtime(rs.getTime("k_endtime"));
			}
			// count = rs.getInt(1);
			// 记录访问次数
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, rs, cnn);
			// 释放语句句柄、连接句柄、结果集
		}
		return uv;
	}

	public static List<UserView> getViewList(String k_usermail, int type, int page)
			throws Exception {
		if (page < 1) {
			page = 1;
		}
		List<UserView> alist = new ArrayList<UserView>();
		Connection cnn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			cnn = DBHandle.getConnection();
			// 获取连接句柄
			ps = cnn.prepareStatement("select * from k_userhistory where k_usermail=? and k_type=? order by k_accessdate desc,k_accesstime desc limit "
					+ (page - 1) * 20 + ",20");
			ps.setString(1, k_usermail);
			ps.setInt(2, type);
			// 创建语句句柄
			rs = ps.executeQuery();
			// 执行查询语句，获取结果集
			while (rs.next()) {
				// 游标指向第一条记录
				UserView uv = new UserView();
				uv.setId(rs.getInt("id"));
				uv.setUsermail(rs.getString("k_usermail"));
				uv.setIp(rs.getString("k_ip"));
				uv.setOs(rs.getString("k_os"));
				uv.setBrowser(rs.getString("k_browser"));
				uv.setUrl(rs.getString("k_url"));
				uv.setAccessdate(rs.getDate("k_accessdate"));
				uv.setAccesstime(rs.getTime("k_accesstime"));
				uv.setEndtime(rs.getTime("k_endtime"));
				alist.add(uv);
			}
			// count = rs.getInt(1);
			// 记录访问次数
		} catch (Exception es) {
			throw es;
			// 直接将异常抛出，由外部程序处理
		} finally {
			DBHandle.closeResource(ps, rs, cnn);
			// 释放语句句柄、连接句柄、结果集
		}
		return alist;
	}

}
